# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
import re


def Read(fileName, valueNum):
    '''read gird data from dat file'''
    fields = ['year', 'month', 'day', 'hour', 'minute', 'second']
    fields.extend(range(valueNum))
    data = pd.read_table(fileName, names=fields,
                         index_col=False, keep_default_na=False)
    data.index = list(data.year)
    return data


def Clean(data):
    '''clean data'''
    updated = data.where(data >= 0, 0)

    return updated


def Write(path, filename, resultData, precision):
    '''write grid data into file with different precision'''
    newPath = path + filename
    # integer
    if precision == 0:
        np.savetxt(newPath, resultData, delimiter='\t', fmt='%6d')
    # float with 2 precision
    elif precision == 1:
        np.savetxt(newPath, resultData, delimiter='\t', fmt='%.2f')
    # float with 4 precision
    elif precision == 2:
        np.savetxt(newPath, resultData, delimiter='\t', fmt='%.4f')
    # string format
    elif precision == 3:
        np.savetxt(newPath, resultData, delimiter='\t', fmt='%19s')
    elif precision == 4:
        np.savetxt(newPath, resultData, delimiter='\n', fmt='%19s')


def GetGaugeMean(timeStart, timeEnd):
    """Get mean of 50 gauge value between timeStart(yyyy-mm-dd_HH:MM:SS)
    and timeEnd(yyyy-mm-dd_HH:MM:SS)
    """
    # read time
    month = {0: 0, 1: 31, 2: 29, 3: 31, 4: 30, 5: 31, 6: 30, 7: 31, 8: 31,
             9: 30, 10: 31, 11: 30, 12: 31}
    start = re.split('-|_|:', timeStart)
    start = [int(s) for s in start]
    end = re.split('-|_|:', timeEnd)
    end = [int(e) for e in end]
    # calculate days of February
    if start[1] >= 2:
        if start[0] % 4 == 0:
            month[2] = 29
        else:
            month[2] = 28
    startIndex = (np.sum([month[i] for i in range(start[1])]) +
                  (start[2] - 1)) * 24 + start[3]
    # + 1 means including the last hour
    endIndex = (np.sum([month[i] for i in range(end[1])]) +
                (end[2] - 1)) * 24 + end[3]

    # read gauge data
    gauge = Read(r"H:/research/rainfall_estimation/data/Gauge"
                 r"/Gauge229_07_10_1h.dat",
                 229)
    subset2008 = gauge[gauge.index == start[0]]
    rng = pd.date_range('1/1/2008', periods=8784, freq='H')
    subset2008.index = rng
    subset2008 = Clean(subset2008)

    # calculate mean value
    gauge50Loc = [10, 13, 15, 22, 26, 38, 41, 43, 49, 60, 61, 62, 64, 66, 77,
                  89, 90, 92, 93, 94, 98, 100, 107, 108, 109, 114, 124, 126,
                  127, 128, 129, 132, 138, 140, 142, 164, 167, 170, 174, 175,
                  177, 178, 181, 204, 205, 206, 212, 219, 220, 230]
    gauge50 = subset2008.iloc[startIndex:(endIndex + 1), gauge50Loc]
    mean = np.mean(gauge50, axis=1)
    return mean


def GetGaugeCenter(timeStart, timeEnd):
    """Get center of 50 gauge between timeStart(yyyy-mm-dd_HH:MM:SS)
    and timeEnd(yyyy-mm-dd_HH:MM:SS)
    """
    # read time
    month = {0: 0, 1: 31, 2: 29, 3: 31, 4: 30, 5: 31,
             6: 30, 7: 31, 8: 31, 9: 30, 10: 31, 11: 30, 12: 31}
    start = re.split('-|_|:', timeStart)
    start = [int(s) for s in start]
    end = re.split('-|_|:', timeEnd)
    end = [int(e) for e in end]
    # calculate days of February
    if start[1] >= 2:
        if start[0] % 4 == 0:
            month[2] = 29
        else:
            month[2] = 28
    startIndex = (np.sum([month[i] for i in range(start[1])]
                         ) + (start[2] - 1)) * 24 + start[3]
    # + 1 means including the last hour
    endIndex = (np.sum([month[i] for i in range(end[1])]) +
                (end[2] - 1)) * 24 + end[3]

    # read gauge data
    gauge = Read(r"H:/research/rainfall_estimation/data/Gauge"
                 r"/Gauge229_07_10_1h.dat", 229)
    subset2008 = gauge[gauge.index == start[0]]
    rng = pd.date_range('1/1/2008', periods=8784, freq='H')
    subset2008.index = rng
    subset2008 = Clean(subset2008)

    # calculate center value
    center = subset2008.iloc[startIndex:(endIndex + 1), 26]
    return center


def Get50Gauge(timeStart, timeEnd):
    """Get 50 gauge value between timeStart(yyyy-mm-dd_HH:MM:SS)
    and timeEnd(yyyy-mm-dd_HH:MM:SS)
    """
    # read time
    month = {0: 0, 1: 31, 2: 29, 3: 31, 4: 30, 5: 31,
             6: 30, 7: 31, 8: 31, 9: 30, 10: 31, 11: 30, 12: 31}
    start = re.split('-|_|:', timeStart)
    start = [int(s) for s in start]
    end = re.split('-|_|:', timeEnd)
    end = [int(e) for e in end]
    # calculate days of February
    if start[1] >= 2:
        if start[0] % 4 == 0:
            month[2] = 29
        else:
            month[2] = 28
    startIndex = (np.sum([month[i] for i in range(start[1])]
                         ) + (start[2] - 1)) * 24 + start[3]
    # + 1 means including the last hour
    endIndex = (np.sum([month[i] for i in range(end[1])]) +
                (end[2] - 1)) * 24 + end[3]

    # read gauge data
    gauge = Read(r"H:/research/rainfall_estimation/data/Gauge"
                 r"/Gauge229_07_10_1h.dat", 229)
    subset2008 = gauge[gauge.index == start[0]]
    rng = pd.date_range('1/1/2008', periods=8784, freq='H')
    subset2008.index = rng
    subset2008 = Clean(subset2008)

    # get 50 gauge value
    gauge50Loc = [10, 13, 15, 22, 26, 38, 41, 43, 49, 60, 61, 62, 64, 66, 77,
                  89, 90, 92, 93, 94, 98, 100, 107, 108, 109, 114, 124, 126,
                  127, 128, 129, 132, 138, 140, 142, 164, 167, 170, 174, 175,
                  177, 178, 181, 204, 205, 206, 212, 219, 220, 230]
    gauge50 = subset2008.iloc[startIndex:(endIndex + 1), gauge50Loc]
    return gauge50


def Get50GaugeCenter(timeStart, timeEnd):
    center = GetGaugeCenter(timeStart, timeEnd)
    return center


def Get50GaugeMean(timeStart, timeEnd):
    mean = GetGaugeMean(timeStart, timeEnd)
    return mean


def Get50GaugeMeanAccum(timeStart, timeEnd):
    mean = GetGaugeMean(timeStart, timeEnd)
    cummean = np.cumsum(mean)
    return cummean


def Get50GaugeCenterAccum(timeStart, timeEnd):
    center = GetGaugeCenter(timeStart, timeEnd)
    cumcenter = np.cumsum(center)
    return cumcenter


if __name__ == '__main__':
    print("Methods for operating gauge data.")
